import { Injectable } from '@nestjs/common';
import CreateUserDto from '../dto/CreateUserDto';
import { Repository, EntityManager } from 'typeorm';
import { InjectRepository } from '@nestjs/typeorm';
import User from '../entity/user.entity';
import RoleApi from './../api/role.api';
import UserRoleLink from '../entity/user_role.link';

@Injectable()
export default class UserService {
  constructor(
    private entityManager: EntityManager,
    @InjectRepository(User)
    private userRepoitory: Repository<User>,
    private roleApi: RoleApi,
    @InjectRepository(UserRoleLink)
    private lUserRoleRepository: Repository<UserRoleLink>,
  ) {}

  async createUser(createUserDto: CreateUserDto) {
    return await this.entityManager.transaction(async (manager) => {
      return await this.create(createUserDto, manager);
    });
  }

  async create(createUserDto: CreateUserDto, manager: EntityManager) {
    const userEntity = await manager.save(
      this.userRepoitory.create({
        email: createUserDto.email,
        name: createUserDto.name,
      }),
    );
    await this.createUserRoles(userEntity.id, createUserDto.roleKeys, manager);
    return userEntity.id;
  }

  async getUserRoleKeys(userId: string) {
    const userRoleLinks = await this.lUserRoleRepository.find({
      where: {
        userId: userId,
      },
    });
    const pros = userRoleLinks.map(async (item:any) => {
      return await this.roleApi.getRoleById(item.roleId);
    });
    return await Promise.all(pros).then((res) => {
      return res.map((item:any) => item.keyword);
    });
  }

  async createUserRoles(
    userId: string,
    roleKeys: string[],
    manager: EntityManager,
  ) {
    const props = roleKeys.map(async (roleKey) => {
      const role = await this.roleApi.getRoleByKey(roleKey);
      if (role.id) {
        manager.save(
          this.lUserRoleRepository.create({
            userId: userId,
            roleId: role.id,
          }),
        );
      }
    });
    await Promise.all(props);
  }

  async getUserByEmail(email: string) {
    const userEntity = await this.userRepoitory.findOne({
      where: { email },
    });
    return userEntity;
  }

  async getRoleKeysByUserId(userId: string) {
    const userRoleLinks = await this.lUserRoleRepository.find({
      where: { userId },
    });
    const roleIds = userRoleLinks.map((item) => {
      return item.roleId;
    });
    const roles = await this.roleApi.getRoleByRoleIds(roleIds);
    return roles.map((item:any) => item.keyword);
  }
}
